/*
 * To change this license header, choose License Headers in Project Properties.
 * To change this template file, choose Tools | Templates
 * and open the template in the editor.
 */
package com.cmti.skeleton.web;

import com.cmti.commons.entity.AuthenticationInfo;
import com.cmti.commons.entity.Right;
import com.cmti.commons.util.HttpUtils;
import com.cmti.commons.util.RequestEndSystemInfo;
import com.cmti.commons.util.StringUtils;
import com.cmti.commons.web.AuthenticationFilter;
import com.cmti.skeleton.dto.SysLogDto;
import com.cmti.skeleton.entity.SysLog;
import com.cmti.skeleton.service.SysLogService;
import java.util.Date;
import java.util.Enumeration;
import java.util.List;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import javax.servlet.http.HttpSession;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.servlet.handler.HandlerInterceptorAdapter;

/**
 *
 * @author danny
 */
public class SysLogInterceptor extends HandlerInterceptorAdapter {

    public static final String SYS_LOG = "SYS_LOG";   // 在request中存储的sysLog的key

    private static final Log log = LogFactory.getLog(SysLogInterceptor.class);

    private boolean enable;

    public boolean isEnable() {
        return enable;
    }

    public void setEnable(boolean enable) {
        this.enable = enable;
    }

    @Autowired
    SysLogService sysLogService;

    @Override
    public void afterCompletion(HttpServletRequest request, HttpServletResponse response, Object handler, Exception ex) throws Exception {
        if (enable) {
            /* 记录模块访问日志 */
            // 获取请求url
            String requestUri = HttpUtils.getInnerRequestUri(request);
            // 获取登录用户权限
            HttpSession session = request.getSession(false);
            AuthenticationInfo user = null;
            if (session != null) {
                user = (AuthenticationInfo) session.getAttribute(AuthenticationFilter.AUTH_INFO);
            }
            if (user != null) {
                List<Right> rightList = user.getRights();
                for (Right right : rightList) {
                    String rUrl = StringUtils.formatNull(right.getUrl());
                    // 只记录模块菜单的日志
                    int wildcardPos = rUrl.indexOf("*");
                    if (wildcardPos < 0) {
//                        rUrl = rUrl.substring(0, wildcardPos);
                        if (requestUri.equals(rUrl)) {
                            // 匹配上权限，构造日志对象
                            SysLogDto sysLog = new SysLogDto();
                            sysLog.setType(SysLog.TYPE_SYSTEM);
                            sysLog.setOperatorId(user.getId().intValue());
                            sysLog.setOperTime(new Date());
                            sysLog.setLogContent(StringUtils.formatNull(right.getLogInfo()));
                            sysLog.setIp(RequestEndSystemInfo.getIpAddr(request));
                            sysLog.setException(ex);
                            if (ex == null) {
                                sysLog.setResult(SysLog.RESULT_SUCCESS);
                            } else {
                                sysLog.setResult(SysLog.RESULT_FAIL);
                            }
                            // 将操作日志记入数据库
                            sysLogService.add(sysLog);
                            // 将详细日志记入日志文件
                            logSysLogDetail(sysLog, request);
                            break;
                        }
                    }
                }
            }
            /* 记录模块访问日志 END */

            // 记录操作日志 
            SysLogDto sysLog = (SysLogDto) request.getAttribute(SYS_LOG);
            if (sysLog != null) {
                request.setAttribute(SYS_LOG, null);    //清除缓存的日志对象
                if (ex != null) {
                    sysLog.setException(ex);
                    sysLog.setResult(SysLog.RESULT_FAIL);
                }
                // 将操作日志记入数据库
                sysLogService.add(sysLog);
                // 将详细日志记入日志文件
                logSysLogDetail(sysLog, request);
            }
        }
    }

    /**
     * 生成syslog实例
     *
     * @param request 用于获取IP，操作者ID等
     * @param type 日志类型
     * @param logContent 日志内容
     * @return the com.cmti.skeleton.dto.SysLogDto
     */
    public static SysLogDto generateSysLog(HttpServletRequest request, Short type, String logContent) {
        SysLogDto sysLog = new SysLogDto();
        sysLog.setOperTime(new Date());
        sysLog.setType(type);
        sysLog.setLogContent(logContent);
        sysLog.setIp(RequestEndSystemInfo.getIpAddr(request));
        AuthenticationInfo user = (AuthenticationInfo) request.getSession().getAttribute(AuthenticationFilter.AUTH_INFO);
        if (user != null) {
            sysLog.setOperatorId(user.getId().intValue());
        } else {
            sysLog.setOperatorId(0);
        }
        // 把日志实例放入request以备后面写入
        request.setAttribute(SYS_LOG, sysLog);
        return sysLog;
    }

    /**
     * 在日志文件中记录详细日志
     *
     * @param sysLog
     * @param request
     */
    public static void logSysLogDetail(SysLogDto sysLog, HttpServletRequest request) {

        //将详细信息记入日志文件
        StringBuilder buf = new StringBuilder("\n[Opration Log Detail]")
                .append("\nDB RECORD ID: ").append(sysLog.getId())
                .append("\n========== Request Param ==========");
        buf.append("\nRequest URI: " + request.getRequestURI() + "\n");
        // log request headers
        buf.append("------ Request Headers ------\n");
        for (Enumeration en = request.getHeaderNames(); en.hasMoreElements();) {
            String name = (String) en.nextElement();
            buf.append(name);
            buf.append(" : ");
            for (Enumeration e = request.getHeaders(name); e.hasMoreElements();) {
                buf.append(e.nextElement());
                buf.append(", ");
            }
            buf.delete(buf.length() - 2, buf.length()).append("\n");
        }
        // log parameters
        buf.append("------ Request Parameters ------\n");
        for (Enumeration en = request.getParameterNames(); en.hasMoreElements();) {
            String name = (String) en.nextElement();
            String values[] = request.getParameterValues(name);
            int n = values.length;
            buf.append(name);
            buf.append(" : ");
            for (int i = 0; i < n; i++) {
                buf.append(values[i]);
                if (i < n - 1) {
                    buf.append(", ");
                }
            }
            buf.append("\n");
        }
        buf.deleteCharAt(buf.length() - 1);
        buf.append("\n========== End ==========");

        log.info(buf.toString(), sysLog.getException());
    }

}
